package cn.swanit.iot.verticles;

import cn.hutool.core.date.DateUtil;
import cn.swanit.iot.contant.EventBusAddress;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.SocketAddress;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * description
 * company 铁人科技
 *
 * @author 陈浩杰
 * @date 2022/11/2 15:20
 */
@Slf4j
@Setter
public class TcpServerVerticle extends AbstractVerticle {

    private NetServer netServer;

    @Override
    public void start(Promise<Void> startPromise) throws Exception {
        log.info("启动TCP服务");
        EventBus eventBus = vertx.eventBus();
        vertx.setPeriodic(1000, id -> {
            eventBus.publish(EventBusAddress.DEMO_ADDRESS, DateUtil.now());
        });

        this.netServer = vertx.createNetServer();

        // 处理连接请求
        netServer.connectHandler(socket -> {
            // 客户端IP和端口
            SocketAddress socketAddress = socket.remoteAddress();
            log.info("客户端连接成功===host==={}===port=={}===", socketAddress.host(), socketAddress.port());

            socket.handler(buffer -> {
                String msg = buffer.toString();
                // 在这里应该解析报文，封装为协议对象，并找到响应的处理类，得到处理结果，并响应
                log.info("接收到的数据为{}", msg);

                // 按照协议响应给客户端
                socket.write(Buffer.buffer("hello client"));
                eventBus.localConsumer(EventBusAddress.DEMO_ADDRESS, mh -> {
                    Object body = mh.body();
                    socket.write(Buffer.buffer(body.toString()));
                });
            });

            // 监听客户端的退出连接
            socket.closeHandler(close -> {
                log.warn("客户端退出连接");
            });

            // 监听客户端的异常退出
            socket.exceptionHandler(e -> {
                log.error("客户端异常退出");
            });
        });

        netServer.exceptionHandler(e -> {
            log.error("服务端异常{}", e.getMessage());
        });

        Integer port = config().getInteger("port");
        String host = config().getString("host");

        // 监听端口
        netServer.listen(port, host).onComplete(successHandler -> {
            startPromise.complete();
        }, failureHandler -> {
            startPromise.fail(failureHandler.getCause());
        });
    }

    @Override
    public void stop(Promise<Void> stopPromise) {
        netServer.close().onComplete(successHandler -> {
            stopPromise.complete();
        }, failureHandler -> {
            stopPromise.fail(failureHandler.getCause());
        });
    }
}
